package wechat

import (
	"caas-platform-payment/internal/consts"
	"caas-platform-payment/internal/dao"
	"caas-platform-payment/internal/model/entity"
	"net/http"
	"strings"

	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/net/ghttp"
	"github.com/nsqio/go-nsq"
	"github.com/wechatpay-apiv3/wechatpay-go/core/auth/verifiers"
	"github.com/wechatpay-apiv3/wechatpay-go/core/downloader"
	"github.com/wechatpay-apiv3/wechatpay-go/core/notify"
)

func (ec *ExtControllerV1) RefundNotify(r *ghttp.Request) {
	// 获取appid
	ctx := r.Context()
	path := strings.TrimSuffix(r.URL.Path, "/")
	segments := strings.Split(path, "/")
	appId := segments[len(segments)-1]
	l.Info(ctx, appId)

	// 通过appid获取商户信息
	// 读取商户信息
	cls := dao.PayChannel.Columns()
	ch := &entity.PayChannel{}
	err := dao.PayChannel.Ctx(ctx).Where(cls.AppId, appId).Where(cls.ChannelName, consts.PayChannels[0].Name).Scan(ch)
	if err != nil || ch.Id == 0 {
		l.Error(ctx, err)
		r.Response.WriteHeader(http.StatusInternalServerError)
		r.Response.WriteJson(g.Map{
			"code":    consts.NotifyAppIdNotExist.Message(),
			"message": consts.NotifyAppIdNotExist.Detail(),
		})
		return
	}

	// 初始化证书访问器
	certVisitor := downloader.MgrInstance().GetCertificateVisitor(ch.MerchantId)
	handler := notify.NewNotifyHandler(ch.MerchantApiKey, verifiers.NewSHA256WithRSAVerifier(certVisitor))

	// 验签和解密
	content := make(map[string]interface{})
	notifyReq, err := handler.ParseNotifyRequest(ctx, r.Request, &content)
	if err != nil {
		l.Error(ctx, err)
		r.Response.WriteHeader(http.StatusInternalServerError)
		r.Response.WriteJson(g.Map{
			"code":    consts.NotifyFailed.Message(),
			"message": consts.NotifyFailed.Detail(),
		})
		return
	}
	// 如果退款不成功直接返回
	if notifyReq.EventType != "REFUND.SUCCESS" {
		r.Response.WriteStatus(http.StatusOK)
		return
	}
	// 反之，如果成功了，则将消息写入nsq
	config := nsq.NewConfig()
	nsqdAddr := g.Cfg().MustGet(ctx, "nsq.address.nsqd").String()
	producer, err := nsq.NewProducer(nsqdAddr, config)
	if err != nil {
		l.Error(ctx, err)
		r.Response.WriteHeader(http.StatusInternalServerError)
		r.Response.WriteJson(g.Map{
			"code":    consts.MsgSendFailed.Message(),
			"message": consts.MsgSendFailed.Detail(),
		})
		return
	}
	defer producer.Stop()
	orderNo := content["out_trade_no"].(string)
	orderSeg := strings.Split(orderNo, consts.SegmentSeperator)
	topic := orderSeg[0] + consts.SegmentSeperator + orderSeg[1] + consts.SegmentSeperator + "refund" + consts.SegmentSeperator + "notify"
	err = producer.Publish(topic, []byte(orderNo+consts.NamedSeperator+notifyReq.EventType))
	if err != nil {
		l.Error(ctx, err)
		r.Response.WriteHeader(http.StatusInternalServerError)
		r.Response.WriteJson(g.Map{
			"code":    consts.MsgSendFailed.Message(),
			"message": consts.MsgSendFailed.Detail(),
		})
		return
	}
	r.Response.WriteStatus(http.StatusOK)
}
